﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Windows.Forms;

namespace zykControl
{
    /// <summary>
    /// 专用于查询并选中一项的文件框控件
    /// </summary>
    [System.ComponentModel.DefaultEvent("FindData")]
    public partial class TxtItem
    {
        /// <summary>
        /// 当值发生改变时发生
        /// </summary>
        [System.ComponentModel.Description("当值发生改变时发生,与FindData配合使用")]
        public event EventHandler ValueChanged;

        /// <summary>
        /// 当控件请求一次查询动作时发生
        /// </summary>
        [System.ComponentModel.Description("当控件请求一次查询动作时发生,与ValueChange配合使用")]
        public event FindDataEventHandler FindData;

        /// <summary>
        /// 当控件请求一次查询动作时发生
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        public delegate void FindDataEventHandler(object sender, TxtItemFindDateArgs e);

        private bool mIsFocuse;

        private void TxtItem_Enter(object sender, EventArgs e)
        {
            TextBox1.Focus();
        }

        private void TextBox1_Click(object sender, EventArgs e)
        {
            OnClick(e);
        }

        private void TextBox1_DoubleClick(object sender, EventArgs e)
        {
            OnDoubleClick(e);
            var dArgs = new TxtItemFindDateArgs("", false);
            FindData?.Invoke(this, dArgs);
            if (dArgs.ToNextFocus) SendKeys.Send("\t");
        }

        private void TextBox1_Enter(object sender, EventArgs e)
        {
            mIsFocuse = true;
            TextBox1.Text = "";
            Label1.Top = TextBox1.Height + 3;
            Height = Label1.Top + Label1.Height;
            if (Value is null)
            {
                TextBox1.BackColor = EmptyBackColor;
            }
            else
            {
                TextBox1.BackColor = FillBackColor;
            }
        }

        private void TxtItem_KeyDown(object sender, KeyEventArgs e)
        {
            OnKeyDown(e);
            if (e.KeyCode == Keys.Enter)
            {
                // If TextBox1.Text = "" AndAlso NullTextToFind = False Then Return
                var dArgs = new TxtItemFindDateArgs(TextBox1.Text, true);
                FindData?.Invoke(this, dArgs);
                if (dArgs.ToNextFocus) SendKeys.Send("\t");
            }
        }

        private void TxtItem_KeyPress(object sender, KeyPressEventArgs e)
        {
            OnKeyPress(e);
            if (e.KeyChar == '\r') e.Handled = true;
        }

        private int mWidthOld;

        private void Label1_DoubleClick(object sender, EventArgs e)
        {
            if (mAllowClear == true & Value is not null)
            {
                SetValueNull();
                Width = Label1.Width + Label1.Left * 2;
                ToolTip1.RemoveAll();
                TextBox1.BackColor = EmptyBackColor;
                TextBox1.Text = "";
            }
        }

        private void Label1_MouseEnter(object sender, EventArgs e)
        {
            mWidthOld = Width;
            Width = Label1.Width + Label1.Left * 2;
            if (mAllowClear && Value is not null)
                ToolTip1.Show("双击此处可清除选定的内容", Label1, 0, Label1.Height, 3000);
        }

        private void Label1_MouseLeave(object sender, EventArgs e)
        {
            Width = mWidthOld;
            ToolTip1.RemoveAll();
        }

        private object? mObject = null;
        private string mDisplayText = "";

        /// <summary>
        /// 返回值
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.Description("返回值")]
        public object? Value
        {
            get
            {
                return mObject;
            }
        }

        /// <summary>
        /// 输入法的允许状态
        /// </summary>
        [System.ComponentModel.Description("输入法的允许状态")]
        public new ImeMode ImeMode
        {
            get
            {
                return TextBox1.ImeMode;
            }

            set
            {
                TextBox1.ImeMode = value;
            }
        }

        /// <summary>
        /// 返回值的文本显示
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.Description("返回值的文本显示")]
        public string DisplayText
        {
            get
            {
                return mDisplayText;
            }
        }

        /// <summary>
        /// 设置/返回文本
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.Description("设置/返回文本"), AllowNull]
        public override string Text
        {
            get
            {
                return TextBox1.Text;
            }
            set
            {
                TextBox1.Text = value;
            }
        }

        /// <summary>
        /// 当设置了值时显示的背景色
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.Description("当设置了值时显示的背景色")]
        public Color FillBackColor { get; set; } = Color.FromArgb(190, 255, 190);
        /// <summary>
        /// 没有设置值时显示的背景色
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.Description("没有设置值时显示的背景色")]
        public Color EmptyBackColor { get; set; } = Color.FromArgb(255, 255, 190);

        /// <summary>
        /// 设置要持有的对象及它的显示文本
        /// </summary>
        /// <param name="theValue"></param>
        /// <param name="theDisplayText"></param>
        public void SetValue(object? theValue, string theDisplayText)
        {
            if (theValue is null)
            {
                SetValueNull();
                return;
            }

            mObject = theValue;
            mDisplayText = theDisplayText;
            if (mIsFocuse)
                TextBox1.Text = "";
            else
                TextBox1.Text = mDisplayText;
            Label1.Text = "已选中: " + mDisplayText;
            TextBox1.BackColor = FillBackColor;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        /// <summary>
        /// 把控件持有的对象清空
        /// </summary>
        public void SetValueNull()
        {
            mObject = null;
            mDisplayText = mNullText;
            if (mIsFocuse)
                TextBox1.Text = "";
            else
                TextBox1.Text = mNullText;
            Label1.Text = "请输入查询内容,然后回车(Enter)";
            TextBox1.BackColor = EmptyBackColor;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void TxtItem_SizeChanged(object sender, EventArgs e)
        {
            Label1.Top = TextBox1.Height + 3;
            if (DesignMode)
            {
                Height = TextBox1.Height;
            }
            else if (mIsFocuse)
            {
                Height = Label1.Top + Label1.Height;
            }
            else
            {
                Height = TextBox1.Height;
            }
        }

        private bool mAllowClear;

        /// <summary>
        /// 双击下部提示栏时,是否允许清除选中项
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.DefaultValue(false)]
        [System.ComponentModel.Description("双击下部提示栏时,是否允许清除选中项")]
        public bool AllowClear
        {
            get
            {
                return mAllowClear;
            }

            set
            {
                mAllowClear = value;
            }
        }

        private string mNullText = "";

        /// <summary>
        /// 当内容为空时显示的文本
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [System.ComponentModel.DefaultValue("")]
        [System.ComponentModel.Description("当内容为空时显示的文本")]
        public string NullText
        {
            get
            {
                return mNullText;
            }

            set
            {
                mNullText = value;
                if (DesignMode == false)
                    return;
                TextBox1.Text = mNullText;
            }
        }

        /// <summary>
        /// 控件是否得到了焦点
        /// </summary>
        public override bool Focused
        {
            get
            {
                return TextBox1.Focused;
            }
        }

        private void TextBox1_Leave(object sender, EventArgs e)
        {
            if (mObject is not null)
            {
                TextBox1.Text = mDisplayText;
            }
            else
            {
                TextBox1.Text = mNullText;
            }

            mIsFocuse = false;
            Height = TextBox1.Height;
            if (Value is null)
            {
                TextBox1.BackColor = EmptyBackColor;
            }
            else
            {
                TextBox1.BackColor = FillBackColor;
            }
        }

        private void TextBox1_SizeChanged(object sender, EventArgs e)
        {
            TxtItem_SizeChanged(sender, e);
        }
    }

    /// <summary>
    /// 用于FindData事件的参数
    /// </summary>
    /// <remarks>
    /// 用于FindData事件的参数
    /// </remarks>
    /// <param name="theInputText"></param>
    /// <param name="theIsKeyPress"></param>
    public class TxtItemFindDateArgs(string theInputText, bool theIsKeyPress) : EventArgs
    {
        /// <summary>返回True表示事件是在文本框当中回车触发的,False表示双击时触发的</summary>
        public readonly bool IsKeyPress = theIsKeyPress;
        /// <summary>被触发时传入的参数</summary>
        public readonly string InputText = theInputText;
        /// <summary>指示是否在完成后把焦点向下一个控件移动</summary>
        public bool ToNextFocus { get; set; }
    }
}